package file

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/utils/upload"
	"github.com/tencentyun/cos-go-sdk-v5"
	"go.uber.org/zap"
	"mime/multipart"
	"path/filepath"
	"strings"
)

// FileService 文件服务
type FileService struct{}

var FileServiceApp = new(FileService)

// UploadFile 上传文件到COS
// 修改为使用已有的UploadFile方法
func (f *FileService) UploadFile(file *multipart.FileHeader, biz string, id string) (map[string]interface{}, error) {
	// 读取文件内容计算MD5
	fileContent, err := file.Open()
	if err != nil {
		global.GVA_LOG.Error("打开文件失败!", zap.Error(err))
		return nil, errors.New("打开文件失败")
	}
	defer fileContent.Close()

	// 创建一个10MB的缓冲区
	buffer := make([]byte, 10*1024*1024)
	hash := md5.New()
	var totalSize int64

	// 修改文件读取循环，正确处理EOF和其他错误
	for {
		n, err := fileContent.Read(buffer)
		if n > 0 {
			hash.Write(buffer[:n])
			totalSize += int64(n)
		}
		if err != nil {
			// 只处理非EOF错误
			if err.Error() != "EOF" {
				global.GVA_LOG.Error("读取文件内容失败!", zap.Error(err))
				return nil, errors.New("读取文件内容失败")
			}
			break
		}
	}

	// 计算文件哈希值
	fileHash := hex.EncodeToString(hash.Sum(nil))

	// 重置文件指针并检查错误
	_, err = fileContent.Seek(0, 0)
	if err != nil {
		global.GVA_LOG.Error("重置文件指针失败!", zap.Error(err))
		return nil, errors.New("重置文件指针失败")
	}

	// 获取文件扩展名
	ext := strings.ToLower(filepath.Ext(file.Filename))

	// 验证图片格式
	validImageTypes := []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"}
	validType := false
	for _, v := range validImageTypes {
		if ext == v {
			validType = true
			break
		}
	}
	if !validType {
		global.GVA_LOG.Error("文件类型不是有效的图片格式!")
		return nil, errors.New("只支持jpg、jpeg、png、gif、bmp、webp格式的图片")
	}

	// 生成文件路径：/{{biz}}/{{id}}/{{hash}}.ext
	fileKey := fmt.Sprintf("%s/%s/%s%s", biz, id, fileHash, ext)

	// 调用通用上传方法
	filePath := global.GVA_CONFIG.TencentCOS.PathPrefix
	if filePath != "" {
		filePath += "/"
	}
	filePath += fileKey

	// 调用COS客户端上传
	_, err = upload.NewClient().Object.Put(
		context.Background(),
		filePath,
		fileContent,
		&cos.ObjectPutOptions{
			ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
				ContentType: global.GVA_CONFIG.TencentCOS.ContentType},
		},
	)
	if err != nil {
		global.GVA_LOG.Error("上传文件到COS失败!", zap.Error(err))
		return nil, errors.New("上传文件到COS失败: " + err.Error())
	}

	// 构建返回结果
	fileURL := global.GVA_CONFIG.TencentCOS.BaseURL
	if fileURL != "" && !strings.HasSuffix(fileURL, "/") && filePath != "" {
		fileURL += "/"
	}
	fileURL += filePath

	result := map[string]interface{}{
		"url":  fileURL,
		"size": totalSize,
		"hash": fileHash,
	}

	return result, nil
}
